/*
 * Created on Nov 3, 2003
 */
package org.vectrics.recruiter.struts;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Locale;

import javax.servlet.jsp.JspException;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.vectrics.SystemException;
import org.vectrics.common.db.DataUtils;
import org.vectrics.common.util.DateSync;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.history.HistoryProvider;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.job.Job;
import org.vectrics.recruiter.job.JobCandidate;
import org.vectrics.recruiter.job.JobCandidateStatusType;
import org.vectrics.recruiter.user.CandidateInfo;
import org.vectrics.recruiter.user.Resume;
import org.vectrics.struts.VectricsActionData;
import org.vectrics.struts.VectricsStrutsAction;
import org.vectrics.user.Person;

public class JobApplyAction extends VectricsStrutsAction {
    private transient static Logger log = Logger.getLogger(JobApplyAction.class);

    @Override
    public String doExecute(final VectricsActionData actionData) throws JspException {
        log.debug("JobApplyAction.doExecute() called");
        boolean hasPrevious = true;
        JobApplicationForm appForm = null;

        ActionForm form = actionData.getForm();
        if (form == null) {
            appForm = new JobApplicationForm();
        } else {
            appForm = (JobApplicationForm) form;
        }

        String forwardCode = null;
        ThreadProperties.getSession().clear();
        Person authPerson = actionData.getAuthPerson();

        String jobIdParam = actionData.getRequest().getParameter("jobId");
        Job job = null;

        if (jobIdParam == null || jobIdParam.trim().length() == 0) {
            jobIdParam = appForm.getJobId();
        }
        if (jobIdParam == null || jobIdParam.length() == 0)
            throw new SystemException("'jobId not valid: " + jobIdParam);
        appForm.setJobId(jobIdParam);

        Long jobId = new Long(jobIdParam);
        job = RecruitServiceLocator.getJobProvider().findJob(jobId);
        if (job == null)
            throw new JspException("Could not find job: " + jobIdParam);
        appForm.setJobTitle(job.getTitle());

        actionData.setRequestForm(appForm);
        Resume createResume = new Resume();
        createResume.setName("* Create New Resume *");
        Collection resumes = null;
        CandidateInfo candidate = RecruitServiceLocator.getRecruitUserService().findCandidateInfo(authPerson);
        if (candidate != null) {
            Collection personResumes = candidate.getResumes();
            resumes = DataUtils.removeVoided(personResumes);
            resumes.add(createResume);
            resumes.addAll(personResumes);
            actionData.getRequest().setAttribute("resumes", resumes);
        }
        boolean personHasResumes = false;
        if (resumes != null && resumes.size() > 0) {
            personHasResumes = true;
        }

        if (appForm.getResumeName() == null || appForm.getResumeName().trim().length() == 0) {
            SimpleDateFormat resumeDateFormat = new SimpleDateFormat("dd/MM/yyyy");
            String resumeName = "Resume " + resumeDateFormat.format(DateSync.getCurrentTime());
            appForm.setResumeName(resumeName);
        }

        if (actionData.wasButtonPressed("prevCover")) {
            forwardCode = "job.apply.resume.select";
            if (appForm.getTextResume() != null && appForm.getTextResume().trim().length() > 0) {
                forwardCode = "job.apply.resume.text";
            } else {
                forwardCode = "job.apply.resume.select";
                hasPrevious = false;
            }
        } else if (actionData.wasButtonPressed("nextCover")) {
            forwardCode = "done";
        } else if (actionData.wasButtonPressed("prevResumeType")) {
            forwardCode = "cancel";
        } else if (actionData.wasButtonPressed("nextResumeType")) {
            if (appForm.getResumeType().equals("text")) {
                forwardCode = "job.apply.resume.text";
            } else {
                forwardCode = "job.apply.resume.upload";
            }
        } else if (actionData.wasButtonPressed("prevResumeText")) {
            forwardCode = "job.apply.resume.type";
        } else if (actionData.wasButtonPressed("nextResumeText")) {
            forwardCode = "job.apply.resume.cover";
        } else if (actionData.wasButtonPressed("prevSelectResume")) {
            forwardCode = "job.apply.resume.type";
        } else if (actionData.wasButtonPressed("nextSelectResume")) {
            if (appForm.getResumeId() == null || appForm.getResumeId().length() == 0) {
                forwardCode = "job.apply.resume.type";
            } else {
                forwardCode = "job.apply.resume.cover";
            }
        } else if (actionData.wasButtonPressed("prevResumeUpload")) {
            forwardCode = "job.apply.resume.type";
        } else if (actionData.wasButtonPressed("nextResumeUpload")) {
            if (uploadResume(appForm, actionData.getAuthPerson())) {
                forwardCode = "job.apply.resume.cover";
            } else {
                log.info("Could not upload, try again");
                forwardCode = "job.apply.resume.upload";
            }
        } else if (actionData.wasButtonPressed("cancel")) {
            forwardCode = "cancel";
        } else {
            hasPrevious = false;
            if (personHasResumes) {
                forwardCode = "job.apply.resume.select";
            } else {
                forwardCode = "job.apply.resume.type";
            }
        }

        if (forwardCode.equals("job.apply.resume.upload")) {
            appForm.setTextResume(null);
        }

        if (forwardCode.equals("done")) {
            saveApplication(appForm, authPerson, actionData.getLocale(), job);
        }
        actionData.getRequest().setAttribute("hasPreviousPage", new Boolean(hasPrevious));
        return forwardCode;
    }

    /**
     * Perform the upload of a resume and save the resume to the database.
     * 
     * @param form
     * @return
     */
    private boolean uploadResume(final JobApplicationForm form, final Person authPerson) {
        boolean success = true;
        Person person = authPerson;
        CandidateInfo candidate = RecruitServiceLocator.getRecruitUserService().findCandidateInfo(person);
        if (candidate == null) {
            candidate = new CandidateInfo();
            candidate.setPerson(authPerson);
            RecruitServiceLocator.getRecruitUserService().updateCandidateInfo(candidate);
        }

        Resume resume = candidate.addResume();
        resume.setName(form.getResumeName());
        try {
            resume.setName(form.getResumeName());
            // log.info("Updating resume after setting name");
            // RecruitServiceLocator.getRecruitUserProvider().updateResume(resume
            // );

            log.info("Reading upload stream for resume content (that will be saved to a fil)");
            InputStream uploadStream = form.getUploadFile().getInputStream();
            RecruitServiceLocator.getRecruitUserService().saveResumeToFile(candidate, resume,
                    form.getUploadFile().getFileName(), uploadStream);

            form.setUploadFile(null);
            form.setResumeId(resume.getId().toString());
        } catch (Exception ex) {
            success = false;
            log.warn("Exception uploading resume", ex);
        }

        return success;

    }

    private void saveApplication(final JobApplicationForm appForm, final Person authPerson, final Locale locale, Job job) {
        ThreadProperties.getSession().clear();
        // authPerson =
        // CoreServiceLocator.getPersonService().findPersonById(authPerson
        // .getId());
        CandidateInfo candidate = RecruitServiceLocator.getRecruitUserService().createCandidateInfoIfNotExist(
                authPerson);
        job = RecruitServiceLocator.getJobProvider().findJob(job.getId());

        if (candidate.getId() == null) {
            RecruitServiceLocator.getRecruitUserService().updateCandidateInfo(candidate);
            ThreadProperties.forcedCommit();
        }

        JobCandidate jobCandidate = job.findJobCandidate(candidate);
        if (jobCandidate == null) {
            jobCandidate = job.addJobCandidate(candidate);
            RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);
            jobCandidate.setStatus(JobCandidateStatusType.STATUS_CANDIDATE_APPLIED, authPerson);
        }
        RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);

        Resume resume = null;
        if (appForm.getResumeId() != null && appForm.getResumeId().trim().length() > 0) {
            resume = RecruitServiceLocator.getRecruitUserService().findResume(new Long(appForm.getResumeId()));
        } else if (appForm.getResumeType().equals("text")) {
            resume = candidate.addResume();
            resume.setName(appForm.getResumeName());
            resume.setLastUpdate(DateSync.getCurrentTime());
            RecruitServiceLocator.getRecruitUserService().saveUploadedResumeToFile(candidate, resume,
                    appForm.getTextResume());
            RecruitServiceLocator.getRecruitUserService().updateCandidateInfo(candidate);
        }

        if (resume == null)
            throw new SystemException("Exception, resume is null after creation");
        jobCandidate.setResume(resume);
        String coverLetter = appForm.getCoverLetter();
        if (coverLetter.length() > JobCandidate.MAX_COVER_LETTER_LENGTH) {
            coverLetter = coverLetter.substring(0, JobCandidate.MAX_COVER_LETTER_LENGTH - 1);
        }
        jobCandidate.setCoverLetter(appForm.getCoverLetter());
        RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);

        HistoryProvider.getInstance().createHistory(Job.OBJECT_TYPE, job.getId().toString(), "job_appl_create",
                authPerson, "Created a new job application: " + job.getTitle());
    }

}
